﻿using System.Net.WebSockets;
using System.Text;
using DataManageSystem.Data;
using HslCommunication;
using HslCommunication.ModBus;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;

namespace DataManageSystem.Controllers.websocket
{
    [Route("ws/getDataByRegisterCode")]
    [ApiController]
    public class RegisterDataController : ControllerBase
    {
        private readonly DeviceDbContext _deviceDbContext;
        private readonly ILogger<RegisterDataController> _logger;

        public RegisterDataController(DeviceDbContext deviceDbContext, ILogger<RegisterDataController> logger)
        {
            _deviceDbContext = deviceDbContext;
            _logger = logger;
        }

        /// <summary>
        ///  建立 WebSocket 连接并定期推送寄存器状态数据
        /// </summary>
        /// <remarks>客户端需要支持 WebSocket 并发送 WebSocket 连接请求</remarks>
        /// <response code="101">WebSocket 连接成功</response>
        /// <response code="400">请求不是 WebSocket 连接</response>
        [HttpGet]
        [ApiExplorerSettings(IgnoreApi = true)] // Swagger 忽略此端点
        public async Task GetWebSocketConnection(CancellationToken cancellationToken)
        {
            if (!HttpContext.WebSockets.IsWebSocketRequest)
            {
                HttpContext.Response.StatusCode = 400;
                return;
            }

            using var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
            _logger.LogInformation("WebSocket 连接已建立");
            await SendRegisterStatusAsync(webSocket, cancellationToken);
        }

        /// <summary>
        /// 发送设备寄存器状态
        /// </summary>
        private async Task SendRegisterStatusAsync(WebSocket webSocket, CancellationToken cancellationToken)
        {
            try
            {
                while (webSocket.State == WebSocketState.Open && !cancellationToken.IsCancellationRequested)
                {
                    string statusReport = GetRegisterStatusReport();
                    byte[] buffer = Encoding.UTF8.GetBytes(statusReport);

                    await webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, cancellationToken);
                    _logger.LogInformation("已发送 WebSocket 数据: {StatusReport}", statusReport);

                    await Task.Delay(5000, cancellationToken); // 每 5 秒推送一次数据
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "WebSocket 连接错误");
            }
        }

        /// <summary>
        /// 获取所有寄存器状态信息
        /// </summary>
        private string GetRegisterStatusReport()
        {
            var registerCodes = _deviceDbContext.TRegisters.Select(r => r.Code).ToList();
            var statusList = registerCodes.Select(ConnectRegister);
            return string.Join(Environment.NewLine, statusList);
        }

        /// <summary>
        /// 连接单个寄存器
        /// </summary>
        private string ConnectRegister(string registerCode)
        {
            try
            {
                var register = _deviceDbContext.TRegisters.FirstOrDefault(r => r.Code == registerCode);
                if (register == null)
                {
                    string msg = $"[错误] 未找到寄存器: {registerCode}";
                    _logger.LogInformation(msg);
                    return msg;
                }

                string ip = register.Address1 ?? string.Empty;
                string port = register.Address2 ?? string.Empty;
                string protocol = register.Address3?.ToLower() ?? string.Empty;
                byte stationCode = (byte)(register.ModbusStation ?? 0);

                if (string.IsNullOrEmpty(ip) || string.IsNullOrEmpty(port) || string.IsNullOrEmpty(protocol))
                {
                    string msg = $"[错误] 寄存器 {registerCode} 连接信息不完整";
                    _logger.LogInformation(msg);
                    return msg;
                }

                string result = protocol switch
                {
                    "modbus" => ConnectModbus(ip, port, stationCode),
                    "mqtt" => ConnectMqtt(ip, port),
                    "tcp" => ConnectTcp(ip, port),
                    "siemens" => ConnectSiemens(ip, port),
                    _ => $"[错误] 未知协议: {protocol}"
                };

                _logger.LogInformation("寄存器 {RegisterCode} 连接结果: {Result}", registerCode, result);
                return result;
            }
            catch (Exception ex)
            {
                string errorMsg = $"[异常] 连接 {registerCode} 失败: {ex.Message}";
                _logger.LogError(ex, errorMsg);
                return errorMsg;
            }
        }

        private string ConnectModbus(string ip, string port, byte stationCode)
        {
            if (!int.TryParse(port, out int portNum))
            {
                string msg = $"[错误] 无效的端口号: {port}";
                _logger.LogInformation(msg);
                return msg;
            }

            try
            {
                using var modbusClient = new ModbusTcpNet(ip, portNum, stationCode);
                var connectResult = modbusClient.ConnectServer();
                string result = connectResult.IsSuccess
                          ? $"[成功] Modbus 设备连接成功: {ip}:{port}，站号: {stationCode}"
                          : $"[失败] Modbus 设备连接失败: {ip}:{port}，站号: {stationCode}，错误: {connectResult.Message}";

                _logger.LogInformation("Modbus 连接结果: {Result}", result);
                return result;
            }
            catch (Exception ex)
            {
                string errorMsg = $"[异常] Modbus 设备连接 {ip}:{port} 失败: {ex.Message}";
                _logger.LogError(ex, errorMsg);
                return errorMsg;
            }
        }

        private string ConnectMqtt(string ip, string port) => $"[模拟] MQTT 设备 {ip}:{port} 连接成功";
        private string ConnectTcp(string ip, string port) => $"[模拟] TCP 设备 {ip}:{port} 连接成功";
        private string ConnectSiemens(string ip, string port) => $"[模拟] Siemens 设备 {ip}:{port} 连接成功";
    }
}
